package com.hw.one.peach.da.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hw.one.component.data.transform.excel.Import;
import com.hw.one.core.result.MsgResult;
import com.hw.one.core.service.PageService;
import com.hw.one.monitor.util.ExcelUtil;
import com.hw.one.peach.da.dao.IPeachSiteDao;
import com.hw.one.peach.da.mongo.IVOCsMongo;
import com.hw.one.unifiedcode.po.UnifiedCodePo;
import com.hw.one.unifiedcode.service.IUnifiedcodeService;
import com.hw.one.util.DateTimeUtil;

/**
  * @author  sjd 
  * @date 创建时间：2017年7月28日 下午3:12:20 
  * @version 1.0.0
  */
@Service(value = "VOCsService")
public class VOCsService extends PageService implements IVOCsService {

	@Resource
	private IVOCsMongo VOCsMongo;
	
	@Resource
	private IUnifiedcodeService unifiedcodeService;

	@Resource
	private IPeachSiteService peachSiteService;
	
	@Resource
	private IPeachSiteDao peachSiteDao;
	
	@Override
	public MsgResult get(Map<String, Object> params) {
		MsgResult result = null;
		try {
			String site = String.valueOf(params.get("siteCode"));
			String device = String.valueOf(params.get("deviceCode"));
			
			boolean isUpload = String.valueOf(params.get("isUpload")).equals("1");
			
			FtpClientUtils ftp = new FtpClientUtils();
			List<Map<String, Object>> data = null;
			if (isUpload) {
				data = ftp.fileList("correction");
			} else {
				data = ftp.fileList("");
			}
			Date dateStart = DateTimeUtil.getFormatDate(String.valueOf(params.get("dateStart")), "yyyy-MM-dd HH");
			Date dateEnd = DateTimeUtil.getFormatDate(String.valueOf(params.get("dateEnd")), "yyyy-MM-dd HH");
			
			String sitecode = null;
			String devicecode = null;
			Date time = null;
			
			Map<String, Object> retMap = new HashMap<String, Object>();
			List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
			
			List<Map<String, Object>> sites = (List<Map<String, Object>>) peachSiteService.get(new HashMap<String, Object>()).getData();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			
			for (Map<String, Object> map : data) {
				String[] strs = String.valueOf(map.get("name")).split("_");
				sitecode = strs[0];
				devicecode = strs[1];
				time = DateTimeUtil.getFormatDate(strs[2].substring(0, 10), "yyyyMMddHH");
				
				// 判断数据所在的站点区间 取出站点名称
				String sitename = "";
				boolean flag = false;
				String code = "", name = "", rangestr = "", start = "", end = "";
				String[] range = null;
				for (Map<String, Object> m : sites) {
					code = String.valueOf(m.get("SITECODE"));
					name = String.valueOf(m.get("SITENAME"));
					
					if (code.equals(sitecode)) {
						rangestr = String.valueOf(m.get("DATESTR"));
						range = rangestr.split(";");
						
						for (String string : range) {
							start = string.split(",")[0];
							end = string.split(",")[1];
							
							if (!time.after(sdf.parse(end)) && !time.before(sdf.parse(start))) {
								sitename = name;
								flag = true;
							}
						}
					}
					
					if (flag) {
						break;
					}
				}
				
				retMap = new HashMap<String, Object>();
				retMap.put("sitecode", sitecode);
				retMap.put("devicecode", devicecode);
				retMap.put("sitename", sitename);
				retMap.put("devicename", devicecode);
				retMap.put("filename", strs[2]);
				retMap.put("filesize", Math.round(Double.parseDouble(String.valueOf(map.get("size"))) / 1024 * 100) / 100 + "KB");
				retMap.put("filetime", map.get("time"));
				
				boolean booldate = (time.after(dateStart) || time.equals(dateStart)) && (time.before(dateEnd) || time.equals(dateEnd));
				boolean boolsite = site == null || "".equals(site) || sitecode.equals(site);
				boolean booldevice = device == null || "".equals(device) || devicecode.equals(device);
				// 查询条件过滤
				if (booldate && boolsite && booldevice) {
					ret.add(retMap);
				}
			}
			
			Collections.sort(ret, new Comparator<Map<String, Object>>() {
				public int compare(Map<String, Object> o1, Map<String, Object> o2) {
					long t1 = 0, t2 = 0;
					try {
						t1 = sdf.parse(String.valueOf(o1.get("filetime"))).getTime();
						t2 = sdf.parse(String.valueOf(o2.get("filetime"))).getTime();
					} catch (Exception e){}
					return (int) (t2 - t1);
				}
			});
			result = MsgResult.okResult(ret);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	@Override
	public MsgResult delete(String filename) {
		FtpClientUtils ftp = null;
		try {
			ftp = new FtpClientUtils();
			ftp.moveFile(filename, "", "delete");
			ftp.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
			ftp.disconnect();
			return MsgResult.errorResult("删除失败");
		}
		return MsgResult.okResult();
	}
	
	/**
	 * 将txt解析为map数据
	 * @param file
	 * @return
	 * @throws IOException 
	 */
	private Map<String, Object> readTxt(MultipartFile file) {
		InputStream is = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		Map<String, Object> ret = new HashMap<String, Object>();
		try {
			is =  file.getInputStream();
			isr = new InputStreamReader(is, "GBK");
			br = new BufferedReader(isr);
			
			String linestr = "";
			List<String> vocs = new ArrayList<String>();
			boolean rec = false;
			while((linestr = br.readLine()) != null) {
				if (!rec && linestr.contains("---------------------")) {
					rec = true;
				} else if (rec && linestr.contains("---------------------")) {
					rec = false;
				} else {
					// vocs数据行
					if (rec && linestr.contains(") ")) {
						vocs.add(linestr);
					}
				}
			}
			
			List<String> components = VOCsEnum.getAllComponent();
			HashMap<String, Object> v = new HashMap<String, Object>();
			for (String vocrow : vocs) {
				vocrow = vocrow.substring(vocrow.indexOf(")") + 2, vocrow.length()).trim().replace("#", "");
				while (vocrow.contains("  ")) {
					vocrow = vocrow.replace("  ", " ");
				}
				String[] vocarr = vocrow.split(" ");
				
				String component = vocarr[0];
				// 转换编码incode为mycode
				Map<String, Object> mapd = new HashMap<String, Object>();
				mapd.put("inCode", component);
				mapd.put("catalogCode", "ITP_VOCS");
				UnifiedCodePo po = unifiedcodeService.getCodeInfo(mapd);
				component = po.getMyCode();
				// 过滤多余的组分
				if (!components.contains(component)) {
					continue;
				}
				
				v = new HashMap<String, Object>();
				if (vocrow.contains("未校正")) {
					v.put("retentionTime", Double.parseDouble(vocarr[1]));
					v.put("quantitativeIon", vocarr[2]);
					v.put("responseValue", Double.parseDouble(vocarr[3]));
					v.put("concentration", 0d);
					v.put("unit", "");
					v.put("deviation", 0d);
				} else if (vocrow.contains("N.D.")) {
					v.put("retentionTime", 0d);
					v.put("quantitativeIon", "");
					v.put("responseValue", 0d);
					v.put("concentration", 0d);
					v.put("unit", "");
					v.put("deviation", 0d);
				} else {
					v.put("retentionTime", Double.parseDouble(vocarr[1]));
					v.put("quantitativeIon", vocarr[2]);
					v.put("responseValue", Double.parseDouble(vocarr[3]));
					v.put("concentration", Double.parseDouble(vocarr[4]));
					v.put("unit", vocarr[5]);
					v.put("deviation", Double.parseDouble(vocarr.length == 6 ? "0" : vocarr[6]));
				}
				
				ret.put(component, v);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
				isr.close();
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return ret;
	}
	
	/**
	 * 递归
	 * @param ret
	 * @param v
	 * @param data
	 */
	public void getChild(HashMap<String, Object> ret, VOCsEnum v, Map<String, Object> data) {
		List<VOCsEnum> vs = VOCsEnum.getChild(v);
		if (vs.size() > 0) {
			HashMap<String, Object> o = new HashMap<String, Object>();
			for (VOCsEnum voCsCat : vs) {
				getChild(o, voCsCat, data);
			}
			ret.put(v.getCode(), o);
		} else {
			ret.put(v.getCode(), data.get(v.getCode()));
		}
	}
	
	/**
	 * 转换为层级结构的vocs数据
	 * @param data
	 * @return
	 */
	public HashMap<String, Object> convert(Map<String, Object> data) {
		HashMap<String, Object> ret = new HashMap<String, Object>();
		
		List<VOCsEnum> tops = VOCsEnum.getRoot();
		for (VOCsEnum voCsCat : tops) {
			getChild(ret, voCsCat, data);
		}
		
		return ret;
	}
	
	@Override
	public void upload(Map<String, Object> params, Map<String, MultipartFile> files) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (String key : files.keySet()) {
			map = this.readTxt(files.get(key));
			
			String timestr = String.valueOf(params.get("monitortime")).substring(0, 10);
			HashMap<String, Object> json = convert(map);
			String siteCode = String.valueOf(params.get("sitecode"));
			String monitorTime = DateTimeUtil.getFormatDateStr(DateTimeUtil.getFormatDate(timestr.substring(0, 10), "yyyyMMddHH"));
			
			Map<String, Object> query = new HashMap<String, Object>();
			query.put("siteCode", siteCode);
			query.put("monitorTime", monitorTime);
			Map<String, Object> site = peachSiteDao.getSiteByCodeAndTime(query);
			
			json.put("siteCode", siteCode);
			json.put("siteName", site.get("SITENAME"));
			json.put("deviceCode", params.get("devicecode"));
			json.put("monitorTime", monitorTime);
			// 存储原始数据
			VOCsMongo.upload(json);
			
			// 单位转换
			Object o = null;
			Map<String, Object> m = null;
			float ppb = 0f;
			float con = 0f;
			for (String str : map.keySet()) {
				o = map.get(str);
				if (o instanceof Map) {
					m = (Map<String, Object>) o;
					if (m.get("concentration") != null && !String.valueOf(m.get("concentration")).equals("")) {
						ppb = Float.parseFloat(String.valueOf(m.get("concentration")));
						// μg/m3 = ppb × M/22.4
						con = ppb * VOCsEnum.getRmmByIncode(str) / 22.4f;
						
						m.put("concentration", con);
					}
					m.put("unit", "μg/m3");
					map.put(str, m);
				}
			}
			
			// 存储转换后数据
			json = convert(map);
			json.put("siteCode", siteCode);
			json.put("siteName", site.get("SITENAME"));
			json.put("deviceCode", params.get("devicecode"));
			json.put("monitorTime", monitorTime);
			VOCsMongo.uploadConvert(json);
			
			FtpClientUtils ftp = null;
			// 将zip包转存到已校正文件夹下
			try {
				String filename = params.get("sitecode") + "_" + params.get("devicecode") + "_" + params.get("monitortime");
				ftp = new FtpClientUtils();
				ftp.moveFile(filename, "", "correction");
				ftp.disconnect();
			} catch (Exception e) {
				e.printStackTrace();
				ftp.disconnect();
			}
		}
	}

	@Override
	public InputStream download(String filename) {
		FtpClientUtils u = null;
		try {
			u = new FtpClientUtils();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return u.downFile(filename);
	}

	public void vocTreeLoop(JSONArray arr, VOCsEnum parent) {
		List<VOCsEnum> vs = VOCsEnum.getChild(parent);
		JSONObject o = new JSONObject();
		if (vs.size() > 0) {
			JSONArray ar = new JSONArray();
			for (VOCsEnum voCsCat : vs) {
				vocTreeLoop(ar, voCsCat);
				o.put("label", parent.getName());
				o.put("value", parent.getCode());
				o.put("children", ar);
				o.put("checked", false);
			}
			
			arr.add(o);
		} else {
			o.put("label", parent.getName());
			o.put("value", parent.getCode());
			o.put("checked", false);
			
			arr.add(o);
		}
	}
	
	@Override
	public JSONArray vocTree() {
		JSONArray arr = new JSONArray();
		for (VOCsEnum voCsEnum : VOCsEnum.getRoot()) {
			vocTreeLoop(arr, voCsEnum);
		}
		return arr;
	}
	
	@Override
	public JSONArray componentJson() {
		JSONArray arr = new JSONArray();
		
		JSONObject obj = new JSONObject();
		for (VOCsEnum voc : VOCsEnum.values()) {
			if (voc.name().contains("COM")) {
				obj = new JSONObject();
				obj.put("name", voc.getName());
				obj.put("value", voc.getCode());
				arr.add(obj);
			}
		}
		return arr;
	}

	@Override
	public void importExcel(Map<String, Object> params, Map<String, MultipartFile> files) throws Exception {
		String key = (String) files.keySet().toArray()[0];
		MultipartFile file = files.get(key);
		// 解析excel
		List<Map<String, Object>> excel = new ArrayList<Map<String, Object>>();
		Import imp = new Import();
		// {"Sheet1":{"voc":[{}, {}}]}
		InputStream xml = this.getClass().getClassLoader().getResourceAsStream("ext/tpl/excel/da/tpl-voc-hour-import.xml");
		Map<String, Object> exceldata = imp.excelToData(xml, file.getInputStream(), file.getOriginalFilename());
		excel = (List<Map<String, Object>>) ((Map<String, Object>)exceldata.get("Sheet1")).get("voc");
		
		String siteCode = String.valueOf(params.get("siteCode"));
		String siteName = String.valueOf(params.get("siteName"));
		String deviceCode = String.valueOf(params.get("deviceCode"));
		Map<String, String> unifiedCode = new HashMap<String, String>();
		Map<String, Object> translate = null;
		Map<String, Object> mapd = null;
		Map<String, Object> con = new HashMap<String, Object>();
		UnifiedCodePo po = null;
		for (Map<String, Object> map : excel) {
			translate = new HashMap<String, Object>();
			// 转换编码incode为mycode
			mapd = new HashMap<String, Object>();
			for (String k : map.keySet()) {
				if (k.equals("monitorTime")) {
					translate.put("monitorTime", map.get("monitorTime"));
				} else if (unifiedCode.containsKey(k)) {
					con = new HashMap<String, Object>();
					con.put("concentration", map.get(k));
					translate.put(unifiedCode.get(k), con);
				} else {
					// 转换编码incode为mycode
					mapd.put("inCode", k);
					mapd.put("catalogCode", "ITP_VOCS");
					po = unifiedcodeService.getCodeInfo(mapd);
					con = new HashMap<String, Object>();
					con.put("concentration", map.get(k));
					translate.put(po.getMyCode(), con);
				}
			}
			
			// 转换时间 2018-07-02 23 => 2018-07-02 23:00:00
			String timestr = String.valueOf(map.get("monitorTime"));
			String monitorTime = DateTimeUtil.getFormatDateStr(DateTimeUtil.getFormatDate(timestr, "yyyy-MM-dd HH"));
			
			// 查询站点名称
			Map<String, Object> query = new HashMap<String, Object>();
			query.put("siteCode", siteCode);
			query.put("monitorTime", monitorTime);
//			Map<String, Object> site = peachSiteDao.getSiteByCodeAndTime(query);
			// 转换后数据
			HashMap<String, Object> json = convert(translate);
			json.put("siteCode", siteCode);
			json.put("siteName", siteName);
			json.put("deviceCode", deviceCode);
			json.put("monitorTime", monitorTime);
			json.put("status", "1");
			json.put("inValidFactors", "");
			VOCsMongo.importExcel(json);
		}
	}
}
